<script setup>
import MapboxMap from '@c/mapbox-map/MapboxMap.vue'
import * as mapboxgl from 'mapbox-gl'
import {
  getCurrentInstance,
  nextTick,
  onMounted,
  onBeforeUnmount,
  reactive,
  ref,
  toRef
} from 'vue'
import { getHelper } from '@u/map/index'
import MapUtils from '@v/one-map/map-utils/MapUtils.vue'
import emitter from '@u/event-bus'
import DetailPopup from '@v/one-map/detail-popup/DetailPopup.vue'
import Vue from 'vue'
import { useMapData } from '@/hooks/useMapData'
import DownloadPopup from '@v/one-map/download-popup'
import QuestionDetails from '@v/one-map/map-utils/question_details/QuestionDetails.vue'
import { queryStatus } from '@api/question'
import { queryMapList } from '@/api/back-management/basemap'
import { Message, Loading } from 'element-ui'
import { PERMISSIONS } from '@/common/user'
import { baseFileUrl } from '@/utils'
import { useOldBuilding } from '@/hooks/useOldBuilding'
import { useBuildingAge } from '@/hooks/useBuildingAge'
import ApplyPopup from '@/views/one-map/apply-popup/ApplyPopup.vue'
import * as turf from '@turf/turf'
import { center, featureCollection, bbox } from '@turf/turf'
import WarningTotalPopup from '@/views/one-map/warning-total-popup/index.vue'
import CatalogDetailPanel from '@/views/one-map/left-catalog-detail/index.vue'
import MapPropertyPopup from '@/views/one-map/map-property-popup/MapPropertyPopup.vue'
import axios from 'axios'
import { getLayerLocateByBuildingId } from '@/api/question'
import { 
  MAP_ID, 
  LAYER_IDS, 
  EVENTS, 
  LAYER_STYLES, 
  DEFAULT_BASE_MAP_CONFIG,
  DEFAULT_BASE_MAP_LIST,
  DEFAULT_AREA_PARAMS,
  DEFAULT_POPUP_CONFIG,
  DEFAULT_MAP_CENTER,
  DEFAULT_MAP_ZOOM,
  DEFAULT_SELECT_BUILDING_STYLE,
  DEFAULT_BUILDING_STYLE
} from './constants'
import { showLoading, closeLoading } from '@/utils/loading'

// [MAP_DRAWING] - 地图绘制相关导入


/**
 * One Map 主组件
 * 
 * 高亮逻辑重构说明：
 * 1. 移除了独立的 SELECTED_BUILDING_HIGHLIGHT 图层
 * 2. 将高亮逻辑集中到特殊图层内部，通过条件样式实现
 * 3. 使用 Mapbox GL JS 的 case 表达式来动态设置样式
 * 4. 简化了代码结构，减少了图层管理的复杂性
 * 
 * 新的高亮流程：
 * - 特殊图层加载时设置默认样式（灰色）
 * - 当有建筑物需要高亮时，通过 updateSpecialLayerHighlight() 更新样式
 * - 使用条件表达式为每个高亮建筑物设置特定颜色
 * - 未高亮的建筑物保持默认样式
 */

let _map
const _layerManager = new Map()
let _infoWindowPopup

// 跟踪通过 loadUrlLayer 加载的图层
const urlLoadedLayers = new Set()

const user = JSON.parse(localStorage.getItem('user')).user

const baseMapConfig = reactive({ ...DEFAULT_BASE_MAP_CONFIG })
const vm = getCurrentInstance()

const { currentUser } = vm?.proxy.$store.state.user

const isMapLoaded = ref(false)
const isMeasureMode = ref(false)

const middlePoint = user?.middlePoint?.split(',')

// 弹窗相关状态
const popupState = reactive({
  visible: false,
  title: '通过',
  propertyList: [],
  name: '测试',
  communityName: '测试社区名称',
  status: ''
})

// 组件引用
const mapUtilsRef = ref()
const questionDetailsRef = ref()

const baseMapList = ref([...DEFAULT_BASE_MAP_LIST])

const specialLayerIds = ref([])

const specialLayerSources = ref({})

const specialSourceLayer = ref('')

const specialLayerUrl = window.BULIDING_LAYER_URL

const selectedBuildingIds = ref([])
const activeBuildingLayers = ref(new Set())
const layerBuildingIds = ref(new Map())
const layerStyleConfigs = ref(new Map())
const layerLabelFeatures = ref(new Map())
const buildingPointMarkers = ref([])
const layerPointMarkers = ref(new Map())

const currentAreaParams = ref({ ...DEFAULT_AREA_PARAMS })

const currentAddIds = ref([])

// 跟踪图层来源：'resource' 表示从资源目录面板加载，'layer' 表示从图层管理面板加载
const layerSourceMap = ref(new Map())

const mapDataStore = useMapData()
const oldBuildingHelper = useOldBuilding()
const buildingAgeHelper = useBuildingAge()

const cache = mapDataStore.getBuildingCache()

// 获取所有活跃建筑物图层的建筑物ID
const getAllActiveBuildingIds = () => Array.from(layerBuildingIds.value.values()).flat()

const allBuildingIdsOriginal = ref([])

const getUrl = (url) => url ? baseFileUrl + url : ''

// 清理高亮图层
const clearHighlightLayer = () => {
  if (_map.getLayer(LAYER_IDS.HIGHLIGHT)) {
    _map.removeLayer(LAYER_IDS.HIGHLIGHT)
  }
  if (_map.getSource(LAYER_IDS.HIGHLIGHT)) {
    _map.removeSource(LAYER_IDS.HIGHLIGHT)
  }
}

const getMapList = () => {
  queryMapList({ pageSize: 999 }).then((res) => {
    if (res.success && res.data?.list) {
      baseMapList.value = res.data.list.map((item) => ({
        type: item.serviceType,
        id: item.pkid,
        name: item.mapName,
        url: item.mapUrl,
        thumbnail: getUrl(item.fileUrl),
      }))
      const defaultItem = res.data.list.find((item) => item.isDefault === 1)
      const targetConfig = defaultItem ? {
        type: defaultItem.serviceType,
        id: defaultItem.pkid,
        name: defaultItem.mapName,
        url: defaultItem.mapUrl,
        thumbnail: getUrl(defaultItem.fileUrl),
      } : baseMapList.value[0]
      Object.assign(baseMapConfig, targetConfig)
    } else {
      Message.error(res.message)
    }
  })
}

onMounted(() => {
  getMapList()
})

const eventHandlers = new Map()
const registerEventHandler = (eventName, handler) => {
  eventHandlers.set(eventName, handler)
  emitter.on(eventName, handler)
}
const cleanupEventHandlers = () => {
  eventHandlers.forEach((handler, eventName) => {
    emitter.off(eventName, handler)
  })
  eventHandlers.clear()
}

onBeforeUnmount(() => {
  cleanupEventHandlers()
  // 清理定时器
  if (updateHighlightTimer) {
    clearTimeout(updateHighlightTimer)
  }
  if (renderLabelsTimer) {
    clearTimeout(renderLabelsTimer)
  }
  // 清理缓存
  labelCentroidsCache.clear()
})

let currentClickHandler = null

const enableBuildingClick = () => {
  if (currentClickHandler) _map.off('click', currentClickHandler)
  currentClickHandler = onBuildingClick
  _map.on('click', currentClickHandler)
}

const disableBuildingClick = () => {
  if (currentClickHandler) _map.off('click', currentClickHandler)
  currentClickHandler = onMapClick
  _map.on('click', currentClickHandler)
}

const NoneClick = () => {
  if (currentClickHandler) _map.off('click', currentClickHandler)
  currentClickHandler = null
}

const initMapClick = () => {
  currentClickHandler = onMapClick
  _map.on('click', currentClickHandler)
}

registerEventHandler(EVENTS.ENABLE_BUILDING_CLICK, enableBuildingClick)
registerEventHandler(EVENTS.DISABLE_BUILDING_CLICK, disableBuildingClick)
registerEventHandler(EVENTS.NONE_CLICK, NoneClick)

const afterMapLoaded = async (id, map) => {
  const helper = await getHelper(id)
  _layerManager.set(id, helper.layerManager)
  _map = map

  emitter.emit('map-ready', map)

  initMapClick()
  map.resize()
  isMapLoaded.value = true

  mapDataStore.init(map, _layerManager)
  oldBuildingHelper.init(map)
  buildingAgeHelper.init(map)

  registerEventHandler(EVENTS.MEASURE_ACTIVATE, (active) => {
    isMeasureMode.value = active
    
    // 如果激活测量模式，清空地图上的高亮和弹窗
    if (active) {
      clearHighlightLayer()
      clearSpecialLayerHighlight()
      clearBuildingPoints()
      removeHighlightBuildingLabels()
      
      // 关闭弹窗
      dialogState.mapPropertyPopup = false
      mapPropertyData.value = {}
    }
  })

  registerEventHandler(EVENTS.TOGGLE_SERVICE, async (info) => {
    // 只清空弹窗，不清空高亮状态
    dialogState.mapPropertyPopup = false
    mapPropertyData.value = {}
    
    await changeLayerByInfo(info)
  })

  registerEventHandler(EVENTS.UPDATE_BUILDING_POINTS, (data) => {
    updateBuildingPoints(data.points, data.deletePoint)
  })

  registerEventHandler(EVENTS.CLEAR_BUILDING_POINTS, () => {
    clearBuildingPoints()
  })



  registerEventHandler(EVENTS.UPDATE_LABEL_LAYER, () => {
    // 更新label图层
    const allLabelFeatures = []
    layerLabelFeatures.value.forEach((features, layerId) => {
      allLabelFeatures.push(...features)
    })
    renderHighlightLabels(allLabelFeatures)
  })

  registerEventHandler(EVENTS.TAB_DETAIL, (info) => {
    if (!info.pkid) return
    if (mapUtilsRef.value?.leftPanelShow) {
      mapUtilsRef.value.openLeftPanel()
    }
    dialogState.detailShow = true
    if (info.type) {
      detailInfo.type = info.type
      detailInfo.id = info.relationId
      detailInfo.info = null
      if (info.type.includes('region')) {
        detailInfo.id = info.pkid
        detailInfo.info = {
          status: info.status,
          regionId: info.relationId,
          name: info.name,
        }
      }
    } else {
      if (info.residenceId) {
        detailInfo.type = 'residence'
        detailInfo.id = info.residenceId
        detailInfo.info = null
      }
    }
    const id = detailInfo.id
    const parmas = getParamsById(id)
    getStatusById(id, parmas.templateType)
  })

  registerEventHandler(EVENTS.TOGGLE_SPECIAL_LAYER, (isChecked) => {
    // 清空地图上的高亮和弹窗
    clearHighlightLayer()
    clearBuildingPoints()
    removeHighlightBuildingLabels()
    
    // 关闭弹窗
    dialogState.mapPropertyPopup = false
    mapPropertyData.value = {}
    
    loadSpecialLayer(isChecked)
  })

  registerEventHandler(EVENTS.CHECK_SPECIAL_LAYER_STATUS, (callback) => {
    const isChecked = specialLayerIds.value.length > 0
    callback(isChecked)
  })

  registerEventHandler(EVENTS.UPDATE_SELECTED_BUILDINGS, (data) => {
    let buildingIds, deleteIds
    if (data && typeof data === 'object' && data.buildingIds) {
      buildingIds = data.buildingIds || []
      deleteIds = data.deleteIds || []
    } else {
      buildingIds = Array.isArray(data) ? data[0] || [] : data || []
      deleteIds = Array.isArray(data) ? data[1] || [] : []
    }
    
    if (deleteIds && deleteIds.length > 0) {
      for (const [catalogId, existingBuildingIds] of layerBuildingIds.value.entries()) {
        const updatedBuildingIds = existingBuildingIds.filter(id => !deleteIds.includes(id))
        layerBuildingIds.value.set(catalogId, updatedBuildingIds)
      }
    }

    const missingBuildingIds = buildingIds.filter((id) => 
      !Array.from(layerBuildingIds.value.values()).some(idsInLayer => idsInLayer.includes(id))
    )

    if (missingBuildingIds.length > 0) {
      if (layerStyleConfigs.value.size === 0) {
        const defaultCatalogId = 'default-catalog'
        layerStyleConfigs.value.set(defaultCatalogId, DEFAULT_SELECT_BUILDING_STYLE)
        layerBuildingIds.value.set(defaultCatalogId, [])
      }
      
      const defaultCatalogId = Array.from(layerStyleConfigs.value.keys())[0]
      if (defaultCatalogId) {
        const existingBuildingIds =
          layerBuildingIds.value.get(defaultCatalogId) || []

        layerBuildingIds.value.set(defaultCatalogId, [
          ...existingBuildingIds,
          ...missingBuildingIds,
        ])
      }
    }

    updateSpecialLayerHighlight(buildingIds, deleteIds)
    // const allLabelFeatures = []
    // layerLabelFeatures.value.forEach((features, layerId) => {
    //   allLabelFeatures.push(...features)
    // })
  })

  registerEventHandler(EVENTS.CLEAR_SELECTED_BUILDINGS, () => {
    clearSpecialLayerHighlight()
  })

  registerEventHandler(EVENTS.REMOVE_SELECTED_BUILDINGS, () => {
    clearSpecialLayerHighlight()
  })

  registerEventHandler(EVENTS.LOCATE_TO_BUILDINGS, (buildingIds) => {
    locateToBuildings(buildingIds)
  })

  registerEventHandler('FLY_TO_CENTER', (data) => {
    if (_map && data.center) {
      _map.flyTo({
        center: data.center,
        // zoom: data.zoom || 16,
        duration: data.duration || 1000
      })
    }
  })


  registerEventHandler(EVENTS.CHANGE_RIGHT_TAB, () => {
    // 只清空弹窗，不清空高亮状态
    dialogState.mapPropertyPopup = false
    mapPropertyData.value = {}
    
    // 清理图层数据，但保留高亮状态
    if (currentAddIds.value.length > 0) {
      updateMapLayers([], currentAddIds.value)
    }
    currentAddIds.value = []

    // 不清空高亮相关的数据，保持选中状态
    // activeBuildingLayers.value.clear()
    // layerBuildingIds.value.clear()
    // layerStyleConfigs.value.clear()
    // layerPointMarkers.value.clear()
    // layerSourceMap.value.clear() // 清理图层来源跟踪

    // if (specialLayerIds.value.length > 0) {
    //   clearSpecialLayer()
    // }
  })

  registerEventHandler(EVENTS.CLOSE_LEFT_PANEL, () => {
    if (dialogState.catalogDetail) {
      dialogState.catalogDetail = false
    }
  })

  registerEventHandler(EVENTS.OPEN_LEFT_PANEL, () => {
    if (!dialogState.catalogDetail && selectedCatalogNode.value) {
      dialogState.catalogDetail = true
    }
  })

  registerEventHandler(EVENTS.CLEAR_BUILDING_LABELS, () => {
    removeHighlightBuildingLabels()
  })

  registerEventHandler(EVENTS.TOGGLE_URL_LAYER, (data) => {
    if (data.isChecked) {
      loadUrlLayer(data)
    } else {
      clearUrlLayer(data)
    }
  })

  initPopup()


}

const detailInfo = reactive({ id: '', type: '', info: null })
mapDataStore.setBuildingCallback(
  async (buildingArr, catalogId, styleConfig) => {
    // 每次触发 setBuildingCallback 时，先把 specialLayer 放到最上层
    if (specialLayerIds.value.length > 0) {
      specialLayerIds.value.forEach((layerId) => {
        if (_map.getLayer(layerId)) {
          // 将 specialLayer 移动到最上层
          _map.moveLayer(layerId);
        }
      });
    }
    
    if (buildingArr.length === 0) {
      layerLabelFeatures.value.delete(catalogId)
      const allLabelFeatures = []
      layerLabelFeatures.value.forEach((features, layerId) => {
        allLabelFeatures.push(...features)
      })
      renderHighlightLabels(allLabelFeatures)
      // Message.warning('暂无数据')
      return
    }
    if (catalogId) {
      activeBuildingLayers.value.add(catalogId)
      
      const buildingIds = buildingArr.flatMap((item) =>
        item.data.flatMap((d) => d.buildings || [])
      )
      if (styleConfig) {
        layerStyleConfigs.value.set(catalogId, styleConfig)
      }

      layerBuildingIds.value.set(catalogId, buildingIds)
      const allBuildingIds = getAllActiveBuildingIds()
      const labelFeatures = []
      const allPoints = [] 

      if (catalogId !== '1z') {
        buildingArr.forEach((item) => {
          if (item.data && item.data.length > 0) {
            item.data.forEach((dataItem) => {
              // 楼栋 label
              if (dataItem.buildings && dataItem.buildings.length > 0) {
                dataItem.buildings.forEach((buildingId) => {
                  labelFeatures.push({
                    type: 'Feature',
                    geometry: { type: 'Point', coordinates: [0, 0] },
                    properties: {
                      name: item.name,
                      buildingId,
                    },
                  })
                })
              }
              // 点 label 和标记
              if (dataItem.points && dataItem.points.length > 0) {
                dataItem.points.forEach((point, index) => {
                  if (Array.isArray(point) && point.length >= 2) {
                    labelFeatures.push({
                      type: 'Feature',
                      geometry: { type: 'Point', coordinates: point },
                      properties: {
                        name: item.name,
                      },
                    })
                    allPoints.push({
                      coordinates: point,
                      id: `${item.pkid}_${index}_${Date.now()}`,
                      pkid: item.pkid,
                      templateId: item.templateId,
                      name: item.name,
                      properties: item
                    })
                  }
                })
              }
            })
          }
        })
      }

      // 保存当前图层的点位数据
      if (allPoints.length > 0) {
        layerPointMarkers.value.set(catalogId, allPoints)
      } else {
        layerPointMarkers.value.delete(catalogId)
      }

      updateBuildingPointsFromLayers()

      layerLabelFeatures.value.set(catalogId, labelFeatures)

      // await locateToBuildings(buildingIds, catalogId)

      _map.once('idle', () => {
        const allLabelFeatures = []
        layerLabelFeatures.value.forEach((features, layerId) => {
          allLabelFeatures.push(...features)
        })
        renderHighlightLabels(allLabelFeatures)
      })

      const isChecked = specialLayerIds.value.length > 0
      if (!isChecked) {
        await loadSpecialLayer(true, false)
        nextTick(() => {
          // 重新应用所有活跃图层的楼栋高亮
          const allBuildingIds = getAllActiveBuildingIds()
          if (allBuildingIds.length > 0) {
            updateSpecialLayerHighlight(allBuildingIds)
          }
        })
      } else {
        // 重新应用所有活跃图层的楼栋高亮
        const allBuildingIds = getAllActiveBuildingIds()
        if (allBuildingIds.length > 0) {
          updateSpecialLayerHighlight(allBuildingIds)
        }
      }
    }
  }
)

// 清除高亮时同步清除 label 图层
const removeHighlightBuildingLabels = () => {
  if (_map?.getLayer('highlight-building-labels'))
    _map.removeLayer('highlight-building-labels')
  if (_map?.getSource('highlight-building-labels'))
    _map.removeSource('highlight-building-labels')
}

// 设置建筑物图层删除回调
mapDataStore.setBuildingRemovedCallback(async (data) => {
  const catalogId = typeof data === 'string' ? data : data.layerId
  
  activeBuildingLayers.value.delete(catalogId)
  layerBuildingIds.value.delete(catalogId)
  layerStyleConfigs.value.delete(catalogId)
  layerLabelFeatures.value.delete(catalogId)
  layerPointMarkers.value.delete(catalogId)

  if (activeBuildingLayers.value.size > 0) {
    updateSpecialLayerHighlight()
    const allLabelFeatures = []
    layerLabelFeatures.value.forEach((features, layerId) => {
      allLabelFeatures.push(...features)
    })
    renderHighlightLabels(allLabelFeatures)
  } else {
    clearSpecialLayerHighlight()
    // clearSpecialLayer()
    clearBuildingPoints()
  }

  updateBuildingPointsFromLayers()
  removeHighlightBuildingLabels()
})

mapDataStore.setMarkerClickCallback((lngLat, feature) => {
  if (feature.properties.pkid && feature.properties.templateId) {
    const layerId = feature.properties.templateId
    handleShowBuildingDetail(feature.properties)
    mapUtilsRef.value?.setHighlightNode(layerId)
  }
})

// 设置图层加载完成回调
mapDataStore.setLayerLoadedCallback((data) => {
  const { layerId, type, features } = data

  if (!features || features.length === 0) {
    return
  }

  if (!currentAddIds.value.includes(layerId)) {
    return
  }

  // 检查 left-catalog-detail 组件的状态
  let shouldLocate = true
  
  if (catalogDetailRef.value) {
    const catalogDetail = catalogDetailRef.value
    
    // 检查区域、状态、搜索内容是否都没有数据
    const hasAreaInfo = catalogDetail.areaInfo && catalogDetail.areaInfo.length > 0
    const hasStatus = catalogDetail.status && catalogDetail.status !== ''
    const hasSearchKeyword = catalogDetail.searchKeyword && catalogDetail.searchKeyword.trim() !== ''
    
    // 只有当区域、状态、搜索内容都没有数据时，才不调用 locateToFeatures
    if (!hasAreaInfo && !hasStatus && !hasSearchKeyword) {
      shouldLocate = false
    }
  }

  // 如果需要定位，则执行定位逻辑
  if (shouldLocate) {
    setTimeout(() => {
      switch (type) {
        case 'marker':
          locateToFeatures(features, {
            featureType: 'marker',
            showMessage: false,
          })
          break

        case 'line':
          locateToFeatures(features, {
            featureType: 'line',
            showMessage: false,
          })
          break

        case 'point':
          locateToFeatures(features, {
            featureType: 'polygon',
            showMessage: false,
          })
          break

        case 'polygon':
          // 对于多面图层，不执行跳转，只显示图层
          // console.log('多面图层加载完成，跳过跳转定位')
          locateToFeatures(features, {
            featureType: 'polygon',
            showMessage: false,
          })
          break
      }
    }, 300)
  }
})

// 标签渲染防抖定时器
let renderLabelsTimer = null;
let labelCentroidsCache = new Map(); // 缓存建筑物质心

const renderHighlightLabels = (labelFeatures) => {
  // 清除之前的防抖定时器
  if (renderLabelsTimer) {
    clearTimeout(renderLabelsTimer);
  }

  // 使用防抖机制
  renderLabelsTimer = setTimeout(() => {
    performLabelRender(labelFeatures);
  }, 150); // 150ms 防抖延迟
};

const performLabelRender = (labelFeatures) => {
  const allLabelFeatures = [];
  // 收集所有需要标签的建筑物
  activeBuildingLayers.value.forEach((catalogId) => {
    const buildingIds = layerBuildingIds.value.get(catalogId) || [];
    const styleConfig = layerStyleConfigs.value.get(catalogId);

    if (buildingIds.length > 0 && styleConfig) {
      buildingIds.forEach((buildingId) => {
        allLabelFeatures.push({
          type: 'Feature',
          geometry: { type: 'Point', coordinates: [0, 0] },
          properties: {
            name: '',
            buildingId: buildingId,
            catalogId: catalogId,
          },
        });
      });
    }
  });

  // 添加其他标签
  if (labelFeatures && labelFeatures.length > 0) {
    allLabelFeatures.push(...labelFeatures);
  }

  if (allLabelFeatures.length === 0) {
    removeHighlightBuildingLabels();
    return;
  }

  // 批量查询建筑物几何信息
  const buildingIds = allLabelFeatures
    .filter(f => f.properties.buildingId)
    .map(f => f.properties.buildingId);

  if (buildingIds.length > 0) {
    // 使用缓存的质心或批量查询
    updateBuildingCentroids(buildingIds);
  }

  // 构建最终的标签要素
  const updatedFeatures = allLabelFeatures
    .map((feature) => {
      // 点直接用原坐标
      if (!feature.properties.buildingId) return feature;

      // 从缓存获取质心
      const cachedCentroid = labelCentroidsCache.get(feature.properties.buildingId);
      if (cachedCentroid) {
        const originalLabelFeature = labelFeatures?.find(
          (f) => f.properties.buildingId === feature.properties.buildingId
        );
        const name = originalLabelFeature
          ? originalLabelFeature.properties.name
          : '';

        return {
          ...feature,
          geometry: { type: 'Point', coordinates: cachedCentroid },
          properties: {
            ...feature.properties,
            name: name,
          },
        };
      }
      return null;
    })
    .filter((f) => f);

  if (updatedFeatures.length === 0) {
    return;
  }

  // 更新标签图层
  updateLabelLayer(updatedFeatures);
};

// 批量更新建筑物质心缓存
const updateBuildingCentroids = (buildingIds) => {
  // 只查询未缓存的建筑物
  const uncachedIds = buildingIds.filter(id => !labelCentroidsCache.has(id));
  
  if (uncachedIds.length === 0) return;

  // 限制查询数量，避免一次查询太多
  const QUERY_BATCH_SIZE = 50;
  const idsToQuery = uncachedIds.slice(0, QUERY_BATCH_SIZE);

  // 查询当前可见的建筑物
  const features = _map.queryRenderedFeatures(undefined, {
    layers: specialLayerIds.value,
  });

  // 批量计算并缓存质心
  features.forEach((feature) => {
    const buildingId = feature.properties.JZWBM || 
                      feature.properties.id || 
                      feature.properties.pkid;
    
    if (buildingId && idsToQuery.includes(buildingId)) {
      try {
        const centroid = turf.centroid(feature);
        labelCentroidsCache.set(buildingId, centroid.geometry.coordinates);
      } catch (e) {
        // 忽略计算错误
      }
    }
  });

  // 清理过大的缓存
  if (labelCentroidsCache.size > 5000) {
    const entriesToKeep = Array.from(labelCentroidsCache.entries()).slice(-3000);
    labelCentroidsCache.clear();
    entriesToKeep.forEach(([id, coords]) => labelCentroidsCache.set(id, coords));
  }
};

// 更新标签图层
const updateLabelLayer = (features) => {
  const sourceId = 'highlight-building-labels';
  const layerId = 'highlight-building-labels';

  if (_map.getSource(sourceId)) {
    // 如果源已存在，只更新数据
    _map.getSource(sourceId).setData({
      type: 'FeatureCollection',
      features: features
    });
    
    // 确保标签图层保持在最上层
    if (_map.getLayer(layerId)) {
      _map.moveLayer(layerId);
    }
  } else {
    // 创建新的源和图层
    _map.addSource(sourceId, {
      type: 'geojson',
      data: { type: 'FeatureCollection', features: features },
    });

    _map.addLayer({
      id: layerId,
      type: 'symbol',
      source: sourceId,
      layout: {
        'text-field': ['get', 'name'],
        'text-size': 12,
        'text-anchor': 'bottom-left',
        'text-allow-overlap': true,
        'text-ignore-placement': true, // 忽略放置冲突，提高性能
        visibility: 'visible',
      },
      paint: {
        'text-color': '#007bff',
        'text-halo-color': '#fff',
        'text-halo-width': 2,
      },
      minzoom: 14, // 设置最小缩放级别，避免在缩放很小时渲染大量标签
    });
    
    // 确保标签图层保持在最上层
    _map.moveLayer(layerId);
  }
};

const handleChangeArea = (params) => {
  currentAreaParams.value = params
  updateMapLayers(currentAddIds.value, [])
}

const diff = (arr1, arr2) => {
  let add = [...arr2.filter((x) => !arr1.includes(x))]
  let del = [...arr1.filter((x) => !arr2.includes(x))]
  return { add, del }
}

// 清除地图上的所有弹窗
const clearAllPopups = () => {
  // 清除 _infoWindowPopup
  if (_infoWindowPopup) {
    _infoWindowPopup.remove()
    _infoWindowPopup = null
  }
  
  // 清除地图上的所有 popup 元素
  const popupElements = document.querySelectorAll('.mapboxgl-popup')
  popupElements.forEach(popup => {
    if (popup && popup.remove) {
      popup.remove()
    }
  })
}

const changeLayerByInfo = async (info) => {
  let { addIds, removeIds, type } = info
  
  // 清除地图上的弹窗
  clearAllPopups()
  
  // 跟踪图层来源
  addIds.forEach((id) => {
    layerSourceMap.value.set(id, type)
  })
  
  removeIds.forEach((id) => {
    layerSourceMap.value.delete(id)
  })
  
  currentAddIds.value = currentAddIds.value.filter(
    (id) => !removeIds.includes(id)
  )

  addIds.forEach((id) => {
    if (!currentAddIds.value.includes(id)) {
      currentAddIds.value.push(id)
    }
  })

  await updateMapLayers(addIds, removeIds)
  
  // 图层切换后，重新应用高亮状态
  const allBuildingIds = getAllActiveBuildingIds()
  if (allBuildingIds.length > 0) {
    updateSpecialLayerHighlight(allBuildingIds)
  }
}

const updateMapLayers = async (addIds, removeIds) => {
  
  // 清除地图上的弹窗
  clearAllPopups()
  
  for (const id of removeIds) {
    await mapDataStore.removeLayerByCatalogId(id)
  }
  for (const id of addIds) {
    await mapDataStore.addLayerByCatalogId(id, currentAreaParams.value)
  }
}

const onBuildingClick = (e) => {
  if (isMeasureMode.value) {
    return
  }

  const features = _map.queryRenderedFeatures(e.point)

  // 先检查楼栋选择图层（这个方法的图层不可能是楼栋选择图层）
  const pointFeature = features.find((f) => f.layer.id === LAYER_IDS.BUILDING_POINT)
  if (pointFeature) {
    // 传递完整的点位信息，包括坐标和属性
    emitter.emit('BUILDING_POINT_CLICK', {
      coordinates: pointFeature.geometry.coordinates,
      properties: pointFeature.properties
    })
    return
  }

  // 过滤掉通过 loadUrlLayer 加载的图层（用于其他逻辑）
  const filteredFeatures = features.filter(feature => !urlLoadedLayers.has(feature.layer.id))

  // 检查是否是楼栋选择模式
  if (filteredFeatures.length > 0) {
    const feature = filteredFeatures[0]
    const layerId = feature.layer.id

    if (
      specialLayerIds.value.includes(layerId)
    ) {
      // 检查当前是否有从资源目录面板加载的图层
      const hasResourceLayer = Array.from(layerSourceMap.value.values()).includes('resource')
      
      // 只有从资源目录面板加载的图层才支持点击楼栋
      if (hasResourceLayer) {
        const buildingId =
          feature.properties.JZWBM ||
          feature.properties.id ||
          feature.properties.pkid ||
          feature.properties.名称

        const buildingData = {
          id: buildingId,
          name:
            feature.properties.name ||
            feature.properties.名称 ||
            feature.properties.楼栋名称 ||
            `楼栋${buildingId}`,
          properties: feature.properties,
          layerId: layerId,
          coordinates: e.lngLat,
        }

        emitter.emit('MAP_BUILDING_CLICK', buildingData)
      } else {
        emitter.emit('MAP_BLANK_CLICK', e.lngLat)
      }
    } else {
      emitter.emit('MAP_BLANK_CLICK', e.lngLat)
    }
  } else {
    emitter.emit('MAP_BLANK_CLICK', e.lngLat)
  }
}

// 获取图层样式
const getLayerStyle = (geometryType) => {
  let style = LAYER_STYLES.point // 默认点样式
  
  if (geometryType === 'Point' || geometryType === 'MultiPoint') {
    style = LAYER_STYLES.point
  } else if (geometryType === 'LineString' || geometryType === 'MultiLineString') {
    style = LAYER_STYLES.line
  } else if (geometryType === 'Polygon' || geometryType === 'MultiPolygon') {
    style = LAYER_STYLES.polygon
  }
  
  return {
    id: LAYER_IDS.HIGHLIGHT,
    source: LAYER_IDS.HIGHLIGHT,
    ...style
  }
}

const onMapClick = async (e) => {
  if (isMeasureMode.value) {
    return
  }
  const features = _map.queryRenderedFeatures(e.point)

  // if (features.length && features[0].source === 'highlight-building-labels') {
  //   return
  // }

  // 先检查楼栋选择图层（这个方法的图层不可能是楼栋选择图层）
  const pointFeature = features.find((f) => f.layer.id === LAYER_IDS.BUILDING_POINT)
  if (pointFeature && pointFeature.properties) {
    // 处理点位点击
    const pointProps = pointFeature.properties
    if (pointProps.pkid && pointProps.templateId) {
      // 显示详情
      handleShowBuildingDetail({
        pkid: pointProps.pkid,
        templateId: pointProps.templateId
      })
      
      
      // 设置高亮节点
      if (pointProps.templateId) {
        mapUtilsRef.value?.setHighlightNode(pointProps.templateId)
      }
    }
    return
  }

  // 过滤掉通过 loadUrlLayer 加载的图层（用于其他逻辑）
  const filteredFeatures = features.filter(feature => !urlLoadedLayers.has(feature.layer.id))

  if (filteredFeatures.length === 0) {
    dialogState.mapPropertyPopup = false
    mapPropertyData.value = {}

    clearHighlightLayer()
    return
  }
  
  // 优先选择面数据，因为面数据通常更重要且容易出现选择问题
  let feature = filteredFeatures[0]
  const polygonFeature = filteredFeatures.find(f => 
    f.geometry.type === 'Polygon' || f.geometry.type === 'MultiPolygon'
  )
  if (polygonFeature) {
    feature = polygonFeature
  }

  // 高亮当前点击的图层
  let layerId = ''
  if (
    filteredFeatures.length > 0 &&
    filteredFeatures[0].sourceLayer === specialSourceLayer.value
  ) {
    const buildingId = filteredFeatures[0].properties['JZWBM']
    const buildingInfo = findBuildingInfoByCode(buildingId, cache)
    layerId = buildingInfo?.templateId

    if (buildingInfo && buildingInfo.pkid && buildingInfo.templateId) {
      handleShowBuildingDetail(buildingInfo)
    }

    const name = feature.properties['JZWMC'] || ''
    const code = feature.properties['JZWBM'] || ''
    const qx = feature.properties['QXMC'] || ''

    const popupContent = `
      <div style="padding:0 20px;">
        <p>名称: ${name}</p>
        <p>编码: ${code}</p>
        <p>区县名称: ${qx}</p>
      </div>
    `

    new mapboxgl.Popup().setLngLat(e.lngLat).setHTML(popupContent).addTo(_map)
  } else {
    layerId = filteredFeatures[0]?.source
    if (feature.properties.pkid && feature.properties.templateId && layerSourceMap.value.get(layerId) === 'resource') {
      handleShowBuildingDetail(feature.properties)
    }
  }
  
  // 除了住房的图层管理的图层都不支持点击
  if (layerSourceMap.value.get(layerId) === 'layer') {
    return;
  }

  if (layerId) {
    mapUtilsRef.value?.setHighlightNode(layerId)
  }

  clearHighlightLayer()

  // 尝试从原始数据源获取完整的 GeoJSON 数据
  let highlightData = feature
  try {
    const sourceId = feature.source
    const source = _map.getSource(sourceId)
    
    if (source && source._data) {
      // 如果是 GeoJSON 数据源，查找匹配的完整要素
      const sourceData = source._data
      
      if (sourceData.type === 'FeatureCollection') {
        // 在 FeatureCollection 中查找匹配的要素
        const matchingFeature = sourceData.features.find(f => {
          // 根据属性匹配（如果有唯一标识）
          if (feature.properties && f.properties) {
            // 优先使用 id 或 pkid 等唯一标识
            if (feature.properties.id && f.properties.id) {
              return feature.properties.id === f.properties.id
            }
            if (feature.properties.pkid && f.properties.pkid) {
              return feature.properties.pkid === f.properties.pkid
            }
            // 如果没有唯一标识，比较所有属性
            return JSON.stringify(feature.properties) === JSON.stringify(f.properties)
          }
          return false
        })
        
        if (matchingFeature) {
          highlightData = matchingFeature
        }
      } else if (sourceData.type === 'Feature') {
        // 单个要素的情况
        highlightData = sourceData
      }
    }
  } catch (error) {
    console.warn('Failed to get complete feature data from source:', error)
  }

  _map.addSource(LAYER_IDS.HIGHLIGHT, {
    type: 'geojson',
    data: highlightData,
  })

  const layerStyle = getLayerStyle(highlightData.geometry.type)
  _map.addLayer(layerStyle)
}

const findBuildingInfoByCode = (code, buildingLayerCache) => {
  for (const [layerId, buildingList] of buildingLayerCache.entries()) {
    for (const item of buildingList) {
      const buildings = item.data[0]?.buildings || []
      if (buildings.includes(code)) {
        return {
          pkid: item.pkid,
          templateId: item.templateId,
        }
      }
    }
  }

  return null
}

// 处理显示楼栋详情
const handleShowBuildingDetail = async (buildingInfo) => {
  try {
    if (mapUtilsRef.value?.leftPanelShow) {
      mapUtilsRef.value.openLeftPanel()
    }

    dialogState.catalogDetail = true

    if (catalogDetailRef.value) {
      catalogDetailRef.value.handleShowBuildingDetailDirect(
        buildingInfo.templateId,
        buildingInfo.pkid
      )
    } else {
      setTimeout(() => {
        catalogDetailRef.value.handleShowBuildingDetailDirect(
          buildingInfo.templateId,
          buildingInfo.pkid
        )
      }, 50)
    }
  } catch (error) {
    Message.error('Failed to load building details')
  }
}

const getParamsById = (id) => {
  const typeMap = {
    'community': { communityId: id, templateType: 'community' },
    'street': { streetId: id, templateType: 'street' },
    'residence': { businessId: id, templateType: 'residence' }
  }
  
  // 查找匹配的类型
  for (const [key, value] of Object.entries(typeMap)) {
    if (detailInfo.type.includes(key)) {
      return value
    }
  }
  
  // 处理region相关类型
  if (detailInfo.type.includes('region-')) {
    return { businessId: id, templateType: detailInfo.type }
  }
  
  return {}
}

const getStatusById = (id, type) => {
  const params = {
    type,
  }
  if (type === 'residence') {
    params.pkid = id
  } else {
    params.relationId = id
  }
  queryStatus(params).then((res) => {
    if (res.success) {
      popupState.status = +Object.keys(res.data)[0]
    }
  })
}

const beforeMapDestroyed = (id, map) => {
  map.off('click', currentClickHandler)
  cleanupEventHandlers()
}

const handleBaseMapChange = (baseMap) => {
  // 清空地图上的高亮和弹窗
  clearHighlightLayer()
  clearSpecialLayerHighlight()
  clearBuildingPoints()
  removeHighlightBuildingLabels()
  
  // 清除地图上的所有弹窗
  clearAllPopups()
  
  // 关闭弹窗
  dialogState.mapPropertyPopup = false
  mapPropertyData.value = {}
  
  Object.assign(baseMapConfig, baseMap)
}

const restoreToHomeLocation = () => {
  _map.easeTo({
    center: middlePoint || DEFAULT_MAP_CENTER,
    zoom: DEFAULT_MAP_ZOOM,
    bearing: 0,
    pitch: 0,
  })
}

const handleDialogClose = (info) => {
  popupState.visible = false
  if (info === 'checked') {
    const id = detailInfo.id
    const parmas = getParamsById(id)
    getStatusById(id, parmas.templateType)
  }
}

const handleApplyClick = () => {
  popupState.title = '通过'
  popupState.visible = true
}

const handleCommunityRegionDetailClick = () => {
  mapUtilsRef.value?.leftPanelShow && mapUtilsRef.value.openLeftPanel()
  dialogState.detailShow = true
}

const handleCommunityAction = (action) => {
  popupState.visible = true
  popupState.title = action
}

const handleCommunityPassClick = () => handleCommunityAction('通过')
const handleCommunityRejectClick = () => handleCommunityAction('驳回')

const initPopup = () => {
  const constructor = Vue.extend(DetailPopup)
  const popupTemplate = new constructor({
    propsData: {
      currentUser,
      propertyList: toRef(popupState, 'propertyList'),
      name: toRef(popupState, 'name'),
      communityName: toRef(popupState, 'communityName'),
      status: toRef(popupState, 'status'),
      handleCommunityRegionDetailClick,
      handleCommunityPassClick,
      handleCommunityRejectClick,
    },
  })
  popupTemplate.$mount()

  _infoWindowPopup = new mapboxgl.Popup(DEFAULT_POPUP_CONFIG).setDOMContent(popupTemplate.$el)
}

// 对话框状态
const dialogState = reactive({
  downloadPopup: false,
  detailShow: false,
  buildTotalPopup: false,
  catalogDetail: false,
  mapPropertyPopup: false
})
const closeDialog = () => {
  dialogState.detailShow = false
  if (!mapUtilsRef.value.leftPanelShow) mapUtilsRef.value.openLeftPanel()
}

const selectedCatalogNode = ref(null)
const catalogDetailRef = ref()
const mapPropertyData = ref({})

const handleShowCatalogDetail = (nodeData) => {
  if (nodeData) {
    selectedCatalogNode.value = nodeData
    dialogState.catalogDetail = true
    dialogState.mapPropertyPopup = false
    mapPropertyData.value = {}

    clearHighlightLayer()
    
    // 重置楼栋详情模式，确保可以正常切换到其他图层
    if (catalogDetailRef.value) {
      catalogDetailRef.value.resetBuildingDetailMode()
      catalogDetailRef.value.clearDrawMapToolData()
    }
  } else {
    dialogState.catalogDetail = false
    selectedCatalogNode.value = null
  }
}

const handleCloseCatalogDetail = () => {
  dialogState.catalogDetail = false
  selectedCatalogNode.value = null
}

const handleCloseMapPropertyPopup = () => {
  dialogState.mapPropertyPopup = false
  mapPropertyData.value = {}

  // 清除地图高亮
  clearHighlightLayer()
}

const clearSpecialLayer = () => {
  clearSpecialLayerHighlight()
  
  // 清除地图上的弹窗
  clearAllPopups()

  const layerIdsToRemove = [...specialLayerIds.value]
  const sourceKeysToRemove = Object.keys(specialLayerSources.value)

  layerIdsToRemove.forEach((id) => {
    if (_map.getLayer(id)) {
      _map.removeLayer(id)
    }
  })

  sourceKeysToRemove.forEach((sourceKey) => {
    if (_map.getSource(sourceKey)) {
      _map.removeSource(sourceKey)
    }
  })

  specialLayerIds.value = []
  specialLayerSources.value = {}
  activeBuildingLayers.value.clear()
  layerBuildingIds.value.clear()
  layerStyleConfigs.value.clear()
  layerPointMarkers.value.clear()
  layerSourceMap.value.clear() // 清理图层来源跟踪
}

// 添加加载状态标记
let isSpecialLayerLoading = false;
let specialLayerLoadPromise = null;

// 添加住房的特殊图层
const loadSpecialLayer = async (isChecked, isAutoLocate = true) => {
  if (!isChecked) {
    clearSpecialLayerHighlight()
    clearSpecialLayer()
    return
  }

  // 如果特殊图层已经加载，直接返回
  if (specialLayerIds.value.length > 0) {
    // 重新应用高亮
    updateSpecialLayerHighlight()
    return
  }

  // 如果正在加载中，等待加载完成
  if (isSpecialLayerLoading && specialLayerLoadPromise) {
    return specialLayerLoadPromise
  }

  // if (isAutoLocate) {
  //   _map.flyTo({
  //     zoom: 14,
  //   })
  // }

  isSpecialLayerLoading = true
  
  specialLayerLoadPromise = (async () => {
    try {
      const response = await axios.get(specialLayerUrl)
      const tileJSON = response.data
      
      // 批量添加源
      specialLayerSources.value = tileJSON.sources
      Object.keys(tileJSON.sources).forEach((sourceKey) => {
        if (!_map.getSource(sourceKey)) {
          _map.addSource(sourceKey, tileJSON.sources[sourceKey])
        }
      })
      
      // 批量添加图层
      tileJSON.layers.forEach((layer) => {
        if (!specialLayerIds.value.includes(layer.id)) {
          specialLayerIds.value.push(layer.id)
          specialSourceLayer.value = layer['source-layer']
          
          // 设置默认样式 - 未高亮的建筑物
          layer.paint = {
            'fill-color': DEFAULT_BUILDING_STYLE.style.paint['fill-color'],
            'fill-opacity': DEFAULT_BUILDING_STYLE.style.paint['fill-opacity'],
            'fill-outline-color': DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color'],
          }
          
          // 确保图层不存在后再添加
          if (!_map.getLayer(layer.id)) {
            _map.addLayer(layer)
          }
        }
      })

      // 图层加载完成后应用高亮
      updateSpecialLayerHighlight()
    } catch (error) {
      console.error('Failed to load special layer:', error)
      // 清理错误状态
      specialLayerIds.value = []
      specialLayerSources.value = {}
    } finally {
      isSpecialLayerLoading = false
      specialLayerLoadPromise = null
    }
  })()

  return specialLayerLoadPromise
}

const copyAllBuildingIds = (allBuildingIds) => {
  allBuildingIdsOriginal.value = JSON.parse(JSON.stringify(allBuildingIds))
}

// 防抖定时器
let updateHighlightTimer = null;
let pendingHighlightUpdate = null;

// 更新特殊图层的高亮状态 - 优化版本
const updateSpecialLayerHighlight = (highlightIds = [], deleteIds = []) => {
  if (!_map || specialLayerIds.value.length === 0) return;

  // 取消之前的防抖定时器
  if (updateHighlightTimer) {
    clearTimeout(updateHighlightTimer);
  }

  // 保存待处理的更新
  pendingHighlightUpdate = { highlightIds, deleteIds };

  // 使用防抖机制，避免频繁更新
  updateHighlightTimer = setTimeout(() => {
    performHighlightUpdate(pendingHighlightUpdate.highlightIds, pendingHighlightUpdate.deleteIds);
    pendingHighlightUpdate = null;
  }, 100); // 100ms 防抖延迟
};

// 懒加载渲染状态管理
let currentRenderTask = null;
let renderQueue = [];
let isRendering = false;

// 获取地图视图范围内的建筑物ID（视图裁剪优化）
const getVisibleBuildingIds = (allBuildingIds) => {
  if (!_map) return allBuildingIds;
  
  try {
    const bounds = _map.getBounds();
    // 如果没有地理边界信息，返回所有ID
    // 这里可以根据实际需要添加更复杂的视图范围检测
    return allBuildingIds;
  } catch (e) {
    return allBuildingIds;
  }
};

// 渐进式渲染：使用 requestIdleCallback 和动态时间片
const processRenderChunk = (task, timeRemaining = 5) => {
  const startTime = performance.now();
  
  // 使用任务配置的时间片大小
  const actualTimeSlice = task.timeSlice || timeRemaining;
  
  while (task.currentIndex < task.data.length && (performance.now() - startTime) < actualTimeSlice) {
    const chunk = task.data.slice(task.currentIndex, task.currentIndex + task.chunkSize);
    
    // 处理当前块
    if (task.type === 'style-update') {
      processStyleChunk(task.layerId, chunk, task.isFirstChunk, task.strategy);
      task.isFirstChunk = false;
    }
    
    task.currentIndex += task.chunkSize;
    task.progress = task.currentIndex / task.data.length;
    
    // 触发进度回调
    if (task.onProgress) {
      task.onProgress(task.progress);
    }
    
    // 对于超大数据量，每处理一个块就让出控制权
    if (task.strategy === 'ultra-lazy') {
      break;
    }
  }
  
  // 如果任务完成
  if (task.currentIndex >= task.data.length) {
    if (task.onComplete) {
      task.onComplete();
    }
    return true; // 任务完成
  }
  
  return false; // 任务未完成
};

// 处理样式块
const processStyleChunk = (layerId, chunk, isFirstChunk, strategy = 'lazy-fast') => {
  if (!_map.getLayer(layerId)) return;
  
  // 对于超大数据量，使用更简单的处理方式
  if (strategy === 'ultra-lazy' && chunk.length > 5) {
    // 分成更小的子块
    const subChunkSize = 5;
    for (let i = 0; i < chunk.length; i += subChunkSize) {
      const subChunk = chunk.slice(i, i + subChunkSize);
      processStyleSubChunk(layerId, subChunk, isFirstChunk && i === 0);
    }
    return;
  }
  
  processStyleSubChunk(layerId, chunk, isFirstChunk);
};

// 处理样式子块
const processStyleSubChunk = (layerId, chunk, isFirstChunk) => {
  const fillColorExpr = ['case'];
  const fillOpacityExpr = ['case'];
  const outlineColorExpr = ['case'];
  
  chunk.forEach(([buildingId, style]) => {
    const condition = ['==', ['get', 'JZWBM'], buildingId];
    fillColorExpr.push(condition, style['fill-color']);
    fillOpacityExpr.push(condition, style['fill-opacity']);
    outlineColorExpr.push(condition, style['fill-outline-color']);
  });
  
  if (isFirstChunk) {
    // 第一块：添加默认样式
    fillColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
    fillOpacityExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
    outlineColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);
  } else {
    // 后续块：使用当前样式作为默认值
    try {
      const currentFillColor = _map.getPaintProperty(layerId, 'fill-color');
      const currentFillOpacity = _map.getPaintProperty(layerId, 'fill-opacity');
      const currentOutlineColor = _map.getPaintProperty(layerId, 'fill-outline-color');
      
      fillColorExpr.push(currentFillColor);
      fillOpacityExpr.push(currentFillOpacity);
      outlineColorExpr.push(currentOutlineColor);
    } catch (e) {
      // 如果获取当前样式失败，使用默认样式
      fillColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
      fillOpacityExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
      outlineColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);
    }
  }
  
  // 批量更新属性
  try {
    _map.setPaintProperty(layerId, 'fill-color', fillColorExpr);
    _map.setPaintProperty(layerId, 'fill-opacity', fillOpacityExpr);
    _map.setPaintProperty(layerId, 'fill-outline-color', outlineColorExpr);
  } catch (e) {
    console.warn(`样式更新失败 [${layerId}]:`, e);
  }
};

// 调度器：管理渲染任务队列
const scheduleRender = () => {
  if (isRendering || renderQueue.length === 0) return;
  
  isRendering = true;
  currentRenderTask = renderQueue.shift();
  
  const renderFrame = (deadline) => {
    const timeRemaining = deadline ? deadline.timeRemaining() : 5;
    
    if (currentRenderTask) {
      const isComplete = processRenderChunk(currentRenderTask, Math.max(timeRemaining, 1));
      
      if (isComplete) {
        currentRenderTask = null;
        isRendering = false;
        
        // 处理下一个任务
        if (renderQueue.length > 0) {
          scheduleRender();
        }
      } else {
        // 根据策略决定下一帧的调度方式
        const strategy = currentRenderTask.strategy;
        let timeout = 100;
        let frameDelay = 16;
        
        switch (strategy) {
          case 'lazy-fast':
            timeout = 50;
            frameDelay = 8;
            break;
          case 'lazy-slow':
            timeout = 200;
            frameDelay = 32;
            break;
          case 'ultra-lazy':
            timeout = 500;
            frameDelay = 64;
            break;
        }
        
        // 继续处理当前任务
        if ('requestIdleCallback' in window) {
          requestIdleCallback(renderFrame, { timeout });
        } else {
          setTimeout(() => renderFrame(), frameDelay);
        }
      }
    }
  };
  
  // 根据任务策略决定初始调度方式
  const strategy = currentRenderTask.strategy;
  let initialTimeout = 100;
  let initialDelay = 16;
  
  switch (strategy) {
    case 'lazy-fast':
      initialTimeout = 50;
      initialDelay = 8;
      break;
    case 'lazy-slow':
      initialTimeout = 200;
      initialDelay = 32;
      break;
    case 'ultra-lazy':
      initialTimeout = 500;
      initialDelay = 64;
      break;
  }
  
  if ('requestIdleCallback' in window) {
    requestIdleCallback(renderFrame, { timeout: initialTimeout });
  } else {
    setTimeout(() => renderFrame(), initialDelay);
  }
};

// 分级性能配置
const PERFORMANCE_LEVELS = {
  SMALL: { threshold: 5000, strategy: 'direct', chunkSize: 5000, timeSlice: 0 },
  MEDIUM: { threshold: 20000, strategy: 'batched', chunkSize: 2000, timeSlice: 0 },
  LARGE: { threshold: 50000, strategy: 'batched', chunkSize: 5000, timeSlice: 0 },
  HUGE: { threshold: 100000, strategy: 'batched', chunkSize: 10000, timeSlice: 0 },
  MASSIVE: { threshold: Infinity, strategy: 'batched', chunkSize: 20000, timeSlice: 0 }
};

// 获取性能级别配置
const getPerformanceLevel = (dataSize) => {
  for (const [key, config] of Object.entries(PERFORMANCE_LEVELS)) {
    if (dataSize <= config.threshold) {
      console.log(`数据量: ${dataSize}, 使用策略: ${config.strategy}`);
      return config;
    }
  }
  return PERFORMANCE_LEVELS.MASSIVE;
};

// 优化的高亮更新函数
const performHighlightUpdate = (highlightIds = [], deleteIds = []) => {
  if (!_map || specialLayerIds.value.length === 0) return;

  // 取消之前的渲染任务
  if (currentRenderTask) {
    currentRenderTask = null;
  }
  renderQueue.length = 0;
  isRendering = false;

  const startTime = performance.now();
  
  // 使用 Set 加速查找
  const highlightSet = new Set(highlightIds);
  const deleteSet = new Set(deleteIds);
  
  // 获取所有建筑物ID
  const allBuildingIds = new Set();
  layerBuildingIds.value.forEach((buildingIds) => {
    buildingIds.forEach(id => {
      if (!deleteSet.has(id)) {
        allBuildingIds.add(id);
      }
    });
  });

  // 视图裁剪优化：只处理可见范围内的建筑物
  const visibleBuildingIds = getVisibleBuildingIds(allBuildingIds);
  const dataSize = visibleBuildingIds.size;
  
  // 根据数据量获取性能配置
  const perfConfig = getPerformanceLevel(dataSize);
  
  // 构建样式映射
  const buildingStyleMap = new Map();
  
  layerBuildingIds.value.forEach((buildingIds, catalogId) => {
    if (!buildingIds || buildingIds.length === 0) return;
 
    const styleConfig = layerStyleConfigs.value.get(catalogId);

    const fillColor = styleConfig?.style?.paint?.['fill-color']?.trim() || '#007bff';
    const outlineColor = styleConfig?.style?.paint?.['fill-outline-color']?.trim() || '#0056b3';
    const baseOpacity = styleConfig?.style?.paint?.['fill-opacity'] ?? 0.4;
    
    buildingIds.forEach((buildingId) => {
      if (visibleBuildingIds.has(buildingId)) {
        const isHighlighted = highlightSet.has(buildingId);
        buildingStyleMap.set(buildingId, {
          'fill-color': catalogId === 'jlp_ljxqjz' ? (getBuildingStatus(buildingId, catalogId) === '2' ? 'red' : fillColor) : fillColor,
          'fill-opacity': isHighlighted ? 0.8 : baseOpacity,
          'fill-outline-color': outlineColor,
        });
      }
    });
  });

  if (buildingStyleMap.size === 0) {
    // 恢复默认样式
    specialLayerIds.value.forEach((layerId) => {
      if (_map.getLayer(layerId)) {
        _map.setPaintProperty(layerId, 'fill-color', DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
        _map.setPaintProperty(layerId, 'fill-opacity', DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
        _map.setPaintProperty(layerId, 'fill-outline-color', DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);
      }
    });
    return;
  }

  // 根据性能策略执行渲染
  switch (perfConfig.strategy) {
    case 'direct':
      performDirectRender(buildingStyleMap, highlightSet, startTime);
      break;
    case 'batched':
      console.log('222')
      performBatchedRender(buildingStyleMap, highlightSet, perfConfig, startTime);
      break;
    case 'lazy-fast':
    case 'lazy-slow':
    case 'ultra-lazy':
      console.log('333')
      performLazyRender(buildingStyleMap, highlightSet, perfConfig, startTime);
      break;
  }

  // 处理删除的楼栋标签
  if (deleteIds.length > 0) {
    const deleteIdSet = new Set(deleteIds);
    layerLabelFeatures.value.forEach((features, layerId) => {
      const newFeatures = features.filter(f => !deleteIdSet.has(f.properties.buildingId));
      layerLabelFeatures.value.set(layerId, newFeatures);
    });
  }
};

// 获取建筑物的状态
const getBuildingStatus = (buildingId, catalogId) => {
  const status = (cache.get(catalogId) || [])
  .find(item => item.data[0].buildings.includes(buildingId))
  ?.status;
  return status
}

// 直接渲染：适用于小数据量（<=5000）
const performDirectRender = (buildingStyleMap, highlightSet, startTime) => {
  const buildingEntries = Array.from(buildingStyleMap.entries());
  
  specialLayerIds.value.forEach((layerId) => {
    if (!_map.getLayer(layerId)) return;

    const fillColorExpr = ['case'];
    const fillOpacityExpr = ['case'];
    const outlineColorExpr = ['case'];

    buildingEntries.forEach(([buildingId, style]) => {
      const condition = ['==', ['get', 'JZWBM'], buildingId];
      fillColorExpr.push(condition, style['fill-color']);
      fillOpacityExpr.push(condition, style['fill-opacity']);
      outlineColorExpr.push(condition, style['fill-outline-color']);
    });
    

    // 默认样式
    fillColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
    fillOpacityExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
    outlineColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);

    // 一次性更新所有属性
    _map.setPaintProperty(layerId, 'fill-color', fillColorExpr);
    _map.setPaintProperty(layerId, 'fill-opacity', fillOpacityExpr);
    _map.setPaintProperty(layerId, 'fill-outline-color', outlineColorExpr);
  });

  const endTime = performance.now();
  console.log(`直接渲染完成: ${(endTime - startTime).toFixed(2)}ms, 建筑物数量: ${buildingStyleMap.size}`);
};

// 分批渲染：适用于中大数据量（5000+），取消懒加载改为快速批量渲染
const performBatchedRender = (buildingStyleMap, highlightSet, perfConfig, startTime) => {
  const buildingEntries = Array.from(buildingStyleMap.entries());
  const batchSize = perfConfig.chunkSize;
  
  specialLayerIds.value.forEach((layerId) => {
    if (!_map.getLayer(layerId)) return;
    
    // 分批处理，但同步执行
    for (let i = 0; i < buildingEntries.length; i += batchSize) {
      const batch = buildingEntries.slice(i, i + batchSize);
      const fillColorExpr = ['case'];
      const fillOpacityExpr = ['case'];
      const outlineColorExpr = ['case'];

      batch.forEach(([buildingId, style]) => {
        const condition = ['==', ['get', 'JZWBM'], buildingId];
        fillColorExpr.push(condition, style['fill-color']);
        fillOpacityExpr.push(condition, style['fill-opacity']);
        outlineColorExpr.push(condition, style['fill-outline-color']);
      });

      if (i === 0) {
        // 第一批：添加默认样式
        fillColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
        fillOpacityExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
        outlineColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);
      } else {
        // 后续批次：使用当前样式作为默认值
        const currentFillColor = _map.getPaintProperty(layerId, 'fill-color');
        const currentFillOpacity = _map.getPaintProperty(layerId, 'fill-opacity');
        const currentOutlineColor = _map.getPaintProperty(layerId, 'fill-outline-color');
        
        fillColorExpr.push(currentFillColor);
        fillOpacityExpr.push(currentFillOpacity);
        outlineColorExpr.push(currentOutlineColor);
      }

      _map.setPaintProperty(layerId, 'fill-color', fillColorExpr);
      _map.setPaintProperty(layerId, 'fill-opacity', fillOpacityExpr);
      _map.setPaintProperty(layerId, 'fill-outline-color', outlineColorExpr);
    }
  });

  const endTime = performance.now();
  console.log(`分批渲染完成: ${(endTime - startTime).toFixed(2)}ms, 建筑物数量: ${buildingStyleMap.size}`);
};

// 懒加载渲染：适用于大数据量（5000+）
const performLazyRender = (buildingStyleMap, highlightSet, perfConfig, startTime) => {
  const buildingEntries = Array.from(buildingStyleMap.entries());
  
  // 优先渲染高亮的建筑物
  const highlightedEntries = buildingEntries.filter(([id]) => highlightSet.has(id));
  const normalEntries = buildingEntries.filter(([id]) => !highlightSet.has(id));
  const sortedEntries = [...highlightedEntries, ...normalEntries];
  
  // 为每个图层创建渲染任务
  specialLayerIds.value.forEach((layerId) => {
    if (!_map.getLayer(layerId)) return;
    
    const task = {
      type: 'style-update',
      layerId: layerId,
      data: sortedEntries,
      currentIndex: 0,
      chunkSize: perfConfig.chunkSize,
      timeSlice: perfConfig.timeSlice,
      isFirstChunk: true,
      progress: 0,
      strategy: perfConfig.strategy,
      onProgress: (progress) => {
        if (progress === 1) {
          console.log(`图层 ${layerId} [${perfConfig.strategy}] 渲染完成`);
        }
      },
      onComplete: () => {
        const endTime = performance.now();
        const duration = endTime - startTime;
        console.log(`${perfConfig.strategy} 渲染完成: ${duration.toFixed(2)}ms, 建筑物数量: ${buildingStyleMap.size}`);
      }
    };
    
    renderQueue.push(task);
  });
  
  // 开始渲染
  scheduleRender();
};

// 同步版本的高亮更新（保留兼容性）
const performSyncHighlightUpdate = (highlightSet, deleteSet, allBuildingIds) => {
  const startTime = performance.now();
  
  // 构建样式映射
  const buildingStyleMap = new Map();
  
  layerBuildingIds.value.forEach((buildingIds, catalogId) => {
    if (!buildingIds || buildingIds.length === 0) return;

    const styleConfig = layerStyleConfigs.value.get(catalogId);
    const fillColor = styleConfig?.style?.paint?.['fill-color']?.trim() || '#007bff';
    const outlineColor = styleConfig?.style?.paint?.['fill-outline-color']?.trim() || '#0056b3';
    const baseOpacity = styleConfig?.style?.paint?.['fill-opacity'] ?? 0.4;

    buildingIds.forEach((buildingId) => {
      if (allBuildingIds.has(buildingId)) {
        const isHighlighted = highlightSet.has(buildingId);
        buildingStyleMap.set(buildingId, {
          'fill-color': fillColor,
          'fill-opacity': isHighlighted ? 0.8 : baseOpacity,
          'fill-outline-color': outlineColor,
        });
      }
    });
  });

  if (buildingStyleMap.size === 0) {
    specialLayerIds.value.forEach((layerId) => {
      if (_map.getLayer(layerId)) {
        _map.setPaintProperty(layerId, 'fill-color', DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
        _map.setPaintProperty(layerId, 'fill-opacity', DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
        _map.setPaintProperty(layerId, 'fill-outline-color', DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);
      }
    });
    return;
  }

  const buildingEntries = Array.from(buildingStyleMap.entries());
  const BATCH_SIZE = 150; // 减小批次大小
  
  specialLayerIds.value.forEach((layerId) => {
    if (!_map.getLayer(layerId)) return;

    if (buildingEntries.length <= BATCH_SIZE) {
      // 小数据量：单次处理
      const fillColorExpr = ['case'];
      const fillOpacityExpr = ['case'];
      const outlineColorExpr = ['case'];

      buildingEntries.forEach(([buildingId, style]) => {
        const condition = ['==', ['get', 'JZWBM'], buildingId];
        fillColorExpr.push(condition, style['fill-color']);
        fillOpacityExpr.push(condition, style['fill-opacity']);
        outlineColorExpr.push(condition, style['fill-outline-color']);
      });

      fillColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-color']);
      fillOpacityExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-opacity']);
      outlineColorExpr.push(DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color']);

      _map.setPaintProperty(layerId, 'fill-color', fillColorExpr);
      _map.setPaintProperty(layerId, 'fill-opacity', fillOpacityExpr);
      _map.setPaintProperty(layerId, 'fill-outline-color', outlineColorExpr);
    } else {
      // 中等数据量：分批处理
      processStyleChunk(layerId, buildingEntries, true);
    }
  });

  const endTime = performance.now();
  const duration = endTime - startTime;
  if (duration > 500) {
    console.warn(`同步渲染耗时: ${duration.toFixed(2)}ms, 建筑物数量: ${buildingStyleMap.size}`);
  }
  
  // 高亮更新完成后，定位到高亮的位置
  // if (highlightIds.length > 0) {
  //   // 获取高亮建筑物的坐标信息
  //   const highlightedBuildingIds = Array.from(highlightSet);
  //   if (highlightedBuildingIds.length > 0) {
  //     // 调用定位函数，跳转到高亮建筑物的位置
  //     locateToBuildings(highlightedBuildingIds);
  //   }
  // }
};


// 清除特殊图层高亮
const clearSpecialLayerHighlight = () => {
  if (!_map || specialLayerIds.value.length === 0) return
  
  specialLayerIds.value.forEach(layerId => {
    if (!_map.getLayer(layerId)) return
    
    // 恢复默认样式
    _map.setPaintProperty(layerId, 'fill-color', DEFAULT_BUILDING_STYLE.style.paint['fill-color'])
    _map.setPaintProperty(layerId, 'fill-opacity', DEFAULT_BUILDING_STYLE.style.paint['fill-opacity'])
    _map.setPaintProperty(layerId, 'fill-outline-color', DEFAULT_BUILDING_STYLE.style.paint['fill-outline-color'])
  })
  
  // 清理数据
  layerBuildingIds.value.clear()
  layerStyleConfigs.value.clear()
  activeBuildingLayers.value.clear()
}

// 这个函数在新的高亮逻辑中不再需要，但保留以防其他地方使用
const splitBuildingsByCatalog = (allBuildingIds) => {
  const result = {}

  layerBuildingIds.value.forEach((buildingIdsInCatalog, catalogId) => {
    const matchedBuildingIds = buildingIdsInCatalog.filter((id) =>
      allBuildingIds.includes(id)
    )
    if (matchedBuildingIds.length > 0) {
      const catalogStyleConfig = layerStyleConfigs.value.get(catalogId) || {}
      result[catalogId] = {
        buildingIds: matchedBuildingIds,
        styleConfig: catalogStyleConfig,
      }

      matchedBuildingIds.forEach((buildingId) => {
        if (catalogStyleConfig[buildingId]) {
          result[catalogId].styleConfig[buildingId] =
            catalogStyleConfig[buildingId]
        }
      })
    }
  })
  return result
}

const updateBuildingPointsFromLayers = () => {
  if (!_map) return

  const allPoints = []
  
  layerPointMarkers.value.forEach((points, catalogId) => {
    if (activeBuildingLayers.value.has(catalogId)) {
      allPoints.push(...points)
    }
  })
  updateBuildingPoints(allPoints)
}

// 更新建筑物点位
const updateBuildingPoints = (points, deletePoint = null) => {
  if (!_map) return

  // 获取当前所有图层的点位
  let allPoints = []
  
  if (deletePoint) {
    layerPointMarkers.value.forEach((points, catalogId) => {
      if (activeBuildingLayers.value.has(catalogId)) {
        // 过滤掉对应的点
        const filteredPoints = points.filter(point =>
          point.coordinates[0] !== deletePoint.coordinates[0] ||
          point.coordinates[1] !== deletePoint.coordinates[1]
        )
        layerPointMarkers.value.set(catalogId, filteredPoints)
      }
    })
  }

  layerPointMarkers.value.forEach((points, catalogId) => {
    if (activeBuildingLayers.value.has(catalogId)) {
      allPoints.push(...points)
    }
  })

  const targetPoints = points || allPoints
  buildingPointMarkers.value = targetPoints
 
  const geojsonData = {
    type: 'FeatureCollection',
    features: allPoints.map((point) => ({
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: point.coordinates,
      },
      properties: {
        id: point.id,
        pkid: point.pkid,
        templateId: point.templateId,
        name: point.name,
        isHighlighted: points.some(targetPoint => targetPoint.id === point.id),
        ...(point.properties || {})
      },
    })),
  }

  // 添加新点位
  const addPoints = points.filter( point => !allPoints.some(p => p.id === point.id))
  const addFeatures = addPoints.map((point) => ({
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: point.coordinates,
    },
    properties: {
      id: point.id, // 确保新增点位也有ID
      isHighlighted: true,
    },
  }))

  geojsonData.features.push(...addFeatures)

  // console.log('geojsonData', geojsonData)

  if (_map.getSource(LAYER_IDS.BUILDING_POINT_SOURCE)) {
    _map.getSource(LAYER_IDS.BUILDING_POINT_SOURCE).setData(geojsonData)
  } else {
    _map.addSource(LAYER_IDS.BUILDING_POINT_SOURCE, {
      type: 'geojson',
      data: geojsonData,
    })
  }

  if (!_map.getLayer(LAYER_IDS.BUILDING_POINT)) {
    _map.addLayer({
      id: LAYER_IDS.BUILDING_POINT,
      type: 'circle',
      source: LAYER_IDS.BUILDING_POINT_SOURCE,
      paint: {
        'circle-radius': 8,
        'circle-color': [
          'case',
          ['==', ['get', 'isHighlighted'], true],
          'rgba(255, 0, 0, 0.8)', // 高亮颜色（透明度0.8）
          'rgba(255, 0, 0, 0.3)' // 默认颜色（半透明）
        ],
        'circle-stroke-color': [
          'case',
          ['==', ['get', 'isHighlighted'], true],
          '#ffffff', // 高亮边框
          'rgba(255, 255, 255, 0.5)' // 默认边框（半透明）
        ],
        'circle-stroke-width': 2,
      },
    })

    _map.on('mouseenter', LAYER_IDS.BUILDING_POINT, () => {
      _map.getCanvas().style.cursor = 'pointer'
    })

    _map.on('mouseleave', LAYER_IDS.BUILDING_POINT, () => {
      _map.getCanvas().style.cursor = ''
    })
  } else {
    // 如果图层已存在，更新样式
    _map.setPaintProperty(LAYER_IDS.BUILDING_POINT, 'circle-color', [
      'case',
      ['==', ['get', 'isHighlighted'], true],
      'rgba(255, 0, 0, 0.8)', // 高亮颜色（透明度0.8）
      'rgba(255, 0, 0, 0.3)' // 默认颜色（半透明）
    ])
    
    _map.setPaintProperty(LAYER_IDS.BUILDING_POINT, 'circle-stroke-color', [
      'case',
      ['==', ['get', 'isHighlighted'], true],
      '#ffffff', // 高亮边框
      'rgba(255, 255, 255, 0.5)' // 默认边框（半透明）
    ])
  }

  // 删除楼栋点位
  if (deletePoint) {
    const coordinates = deletePoint.coordinates
    layerLabelFeatures.value.forEach((features, layerId) => {
      const newFeatures = features.filter(f => f.geometry.coordinates[0] !== coordinates[0] || f.geometry.coordinates[1] !== coordinates[1])
      layerLabelFeatures.value.set(layerId, newFeatures)
    })
  }
}

// 清除建筑物点位
const clearBuildingPoints = () => {
  if (!_map) return

  buildingPointMarkers.value = []

  if (_map.getLayer(LAYER_IDS.BUILDING_POINT)) {
    _map.removeLayer(LAYER_IDS.BUILDING_POINT)
  }

  if (_map.getSource(LAYER_IDS.BUILDING_POINT_SOURCE)) {
    _map.removeSource(LAYER_IDS.BUILDING_POINT_SOURCE)
  }
}


// 定位到选中楼栋
const locateToBuildings = async (buildingIds, layer) => {
  // console.log('buildingIds', buildingIds)
  if (!_map || buildingIds.length === 0) {
    Message.warning('请选择要定位的楼栋！')
    return
  }
  showLoading()
  const res = await getLayerLocateByBuildingId(buildingIds)
  closeLoading()
  if (res.data.length > 0) {
    const allCoordinates = res.data.map((item) => {
      const pointObj = JSON.parse(item.point)
      return pointObj.coordinates.slice(0, 2)
    })
    
    const lons = allCoordinates.map((c) => c[0])
    const lats = allCoordinates.map((c) => c[1])
    const minLng = Math.min(...lons)
    const maxLng = Math.max(...lons)
    const minLat = Math.min(...lats)
    const maxLat = Math.max(...lats)

    const bounds = [
      [minLng, minLat],
      [maxLng, maxLat],
    ]
    
    if (layer === '1z') {
      _map.flyTo({
        center: allCoordinates.length? allCoordinates[0] : [114.31, 30.57],
        // zoom: 16,
        duration: 1000,
      })
    } else {
      const zoom = _map.getZoom();
      _map.fitBounds(bounds, {
        padding: 100,
        zoom: zoom, // 锁定缩放级别
        duration: 1000 // 0 表示瞬间跳过去
      });
    }

    _map.once('idle', () => {
      const allLabelFeatures = []
      layerLabelFeatures.value.forEach((features, layerId) => {
        allLabelFeatures.push(...features)
      })
      renderHighlightLabels(allLabelFeatures)
    })
  }
}

// 通用定位函数 - 根据不同类型的数据采用不同的定位策略
const locateToFeatures = (features, options = {}) => {
  if (!_map || !features || features.length === 0) {
    return
  }

  const {
    featureType = 'auto', //  'marker', 'line', 'polygon', 'auto'
    zoom = 16,
    duration = 1500,
    showMessage = true,
  } = options

  try {
    let centerPoint = null
    let targetZoom = zoom

    // 自动检测要素类型
    let detectedType = featureType
    if (featureType === 'auto' && features.length > 0) {
      const firstFeature = features[0]
      if (firstFeature.geometry) {
        const geometryType = firstFeature.geometry.type
        if (geometryType === 'Point' || geometryType === 'MultiPoint') {
          detectedType = 'marker'
        } else if (
          geometryType === 'LineString' ||
          geometryType === 'MultiLineString'
        ) {
          detectedType = 'line'
        } else if (
          geometryType === 'Polygon' ||
          geometryType === 'MultiPolygon'
        ) {
          detectedType = 'polygon'
        }
      } else if (
        firstFeature.lngLat ||
        (firstFeature.lng && firstFeature.lat)
      ) {
        detectedType = 'marker'
      }
    }

    switch (detectedType) {
      case 'marker': {
        // Marker点位 - 跳转到第一个marker的位置
        const firstMarker = features[0]
        if (firstMarker.lngLat) {
          centerPoint = [firstMarker.lngLat.lng, firstMarker.lngLat.lat]
        } else if (firstMarker.lng && firstMarker.lat) {
          centerPoint = [firstMarker.lng, firstMarker.lat]
        } else if (
          firstMarker.geometry &&
          firstMarker.geometry.type === 'Point'
        ) {
          centerPoint = firstMarker.geometry.coordinates
        }
        targetZoom = 18
        if (showMessage) {
          Message.success('已定位到标记点')
        }
        break
      }

      case 'line':
      case 'polygon':
      default:
        // 线、面数据 - 跳转到所有要素的中心
        if (features.length === 1) {
          // 单个要素，计算其质心
          const centroid = center(features[0])
          centerPoint = centroid.geometry.coordinates
          targetZoom = detectedType === 'line' ? 16 : 17
        } else {
          // 多个要素，计算边界框中心
          const collection = featureCollection(features)
          const bboxCoords = bbox(collection)
          centerPoint = [
            (bboxCoords[0] + bboxCoords[2]) / 2,
            (bboxCoords[1] + bboxCoords[3]) / 2,
          ]

          // 根据边界框大小调整缩放级别
          const lngDiff = bboxCoords[2] - bboxCoords[0]
          const latDiff = bboxCoords[3] - bboxCoords[1]
          const maxDiff = Math.max(lngDiff, latDiff)

          if (maxDiff > 0.01) targetZoom = 12
          else if (maxDiff > 0.005) targetZoom = 14
          else if (maxDiff > 0.001) targetZoom = 16
          else targetZoom = 17
        }

        if (showMessage) {
          const typeText = detectedType === 'line' ? '线要素' : '面要素'
          Message.success(`已定位到${typeText}中心`)
        }
        break
    }

    if (centerPoint) {
      _map.easeTo({
        center: centerPoint,
        // zoom: targetZoom,
        pitch: 0,
        bearing: 0,
        duration: duration,
      })
    }
  } catch (error) {
    if (showMessage) {
      Message.error('定位失败，请重试')
    }
  }
}


const loadUrlLayer = async (data) => {
  if (!data.isChecked) {
    clearUrlLayer(data);
    return;
  }

  await restoreToHomeLocation();

  try {
    const response = await axios.get(data.url);
    const tileJSON = response.data;

    Object.keys(tileJSON.sources).forEach((sourceKey) => {
      if (!_map.getSource(sourceKey)) {
        _map.addSource(sourceKey, tileJSON.sources[sourceKey]);
      }
    });

    for (const layer of tileJSON.layers) {
      if (_map.getLayer(layer.id)) {
        _map.removeLayer(layer.id);
      }

      _map.addLayer({
        id: layer.id,
        type: layer.type,
        source: layer.source,
        'source-layer': layer['source-layer'],
        layout: layer.layout || {},
        paint: layer.paint || {},
        filter: ['==', '区县', user.areaName] 
      });

      // 将图层添加到 urlLoadedLayers 集合中
      urlLoadedLayers.add(layer.id);

      await new Promise((resolve) => {
        const checkLayerRendered = () => {
          if (_map.isSourceLoaded(layer.source) && _map.areTilesLoaded()) {
            _map.once('idle', () => {
              setTimeout(resolve, 200);
            });
          } else {
            setTimeout(checkLayerRendered, 100);
          }
        };
        checkLayerRendered();
      });

      // 查询当前渲染的要素
      const renderedFeatures = _map.queryRenderedFeatures({
        layers: [layer.id]
      });

      if (renderedFeatures.length === 0) {
        _map.setFilter(layer.id, null);
      }
    }

  } catch (error) {
    console.error('Error loading TileJSON data', error);
  }
};

const clearUrlLayer = async (data) => {
  try {
    const response = await axios.get(data.url);
    const tileJSON = response.data;

    tileJSON.layers.forEach((layer) => {
      if (_map.getLayer(layer.id)) {
        _map.removeLayer(layer.id);
        // 从 urlLoadedLayers 集合中移除图层
        urlLoadedLayers.delete(layer.id);
      }
    });

    Object.keys(tileJSON.sources).forEach((sourceKey) => {
      if (_map.getSource(sourceKey)) {
        _map.removeSource(sourceKey);
      }
    });

  } catch (error) {
    console.error('Error clearing TileJSON data', error);
  }
};


</script>

<template>
  <div class="main-container one-map">
    <div id="amap-container"></div>
    <MapboxMap
      :map-id="MAP_ID"
      :base-map-config="baseMapConfig"
      @after-map-loaded="afterMapLoaded"
      @before-map-destroyed="beforeMapDestroyed"
      :show-search="true"
    >
      <template #extra-item>
        <el-button
          type="primary"
          v-if="currentUser?.hasPermission(PERMISSIONS.一张图下载)"
          icon="el-icon-download"
          class="download-button"
          @click="dialogState.downloadPopup = true"
          >{{ currentUser?.getButtonName(PERMISSIONS.一张图下载) }}
        </el-button>

        <el-button
          type="primary"
          v-if="currentUser?.hasPermission(PERMISSIONS.一张图隐患楼宇统计)"
          class="download-button build-total"
          @click="dialogState.buildTotalPopup = true"
        >
          <svg-icon icon-class="build-total" />
          {{ currentUser?.getButtonName(PERMISSIONS.一张图隐患楼宇统计) }}
        </el-button>
      </template>
    </MapboxMap>

    <MapUtils
      v-if="isMapLoaded"
      ref="mapUtilsRef"
      :map-id="MAP_ID"
      :base-map-config="baseMapConfig"
      :base-map-list="baseMapList"
      @restore-to-home-location="restoreToHomeLocation"
      @update:base-map-config="handleBaseMapChange"
      @show-catalog-detail="handleShowCatalogDetail"
      @node-check="loadSpecialLayer"
    />



    <warning-total-popup
      :visible="dialogState.buildTotalPopup"
      @close="dialogState.buildTotalPopup = false"
    />

    <question-details
      ref="questionDetailsRef"
      :detailInfo="detailInfo"
      v-show="dialogState.detailShow"
      :status="popupState.status"
      @closeDialog="closeDialog"
      @applyRecord="handleApplyClick"
    />

    <apply-popup
      :visible="popupState.visible"
      :pkid="detailInfo.id"
      :type="detailInfo.type"
      :title="popupState.title"
      @closeDialog="handleDialogClose"
    />

    <catalog-detail-panel
      ref="catalogDetailRef"
      :visible="dialogState.catalogDetail"
      :selected-node="selectedCatalogNode"
      :all-building-ids="Array.from(layerBuildingIds.values())"
      @close="handleCloseCatalogDetail"
      @change-area="handleChangeArea"
      @copy-all-building-ids="copyAllBuildingIds"
    />

    <map-property-popup
      :visible="dialogState.mapPropertyPopup"
      :properties="mapPropertyData"
      @close="handleCloseMapPropertyPopup"
    />
  </div>
</template>

<style scoped lang="scss">
.one-map {
  position: relative;
  overflow: hidden;
  height: 100%;
  $primary-color: #006fff;

  #amap-container {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
  }

  .mapbox-map {
    width: 100%;
    height: 100%;
  }

  :deep(.mapbox-map) {
    position: absolute;

    .download-button {
      position: relative;
      left: 460px;
      top: 20px;
      //color: white;
      //background: #00c3ff;
      //border: none;
      z-index: 100;

      &.build-total {
        margin-left: 20px;
      }
    }

    .search-area {
      position: relative;
      margin-left: 20px;
      left: 460px;
      top: 20px;
      z-index: 100;
      display: inline-flex;
    }
  }

  :deep {
    .amap-copyright,
    .amap-logo {
      z-index: 0;
    }

    // 社区管辖边界弹窗
    .info-window__wrapper {
      //background-image: url('~@/assets/images/one-map/community-region-popup-background.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;

      .mapboxgl-popup-content {
        display: flex;
        flex-direction: column;

        padding: 15px 18px;

        .name__wrapper {
          display: flex;
          align-items: center;

          width: 262px;
          height: 35px;
          justify-content: space-between;
          background-image: url('~@/assets/images/one-map/community-region-popup-name-background.png');
          background-size: 100% 100%;
          background-repeat: no-repeat;

          .name {
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;

            flex: 1;
            margin-left: 21px;
            font-size: 14px;
            font-family: Microsoft YaHei;
            font-weight: bold;
            line-height: 14px;
            color: black;
          }

          .detail {
            font-size: 14px;
            font-family: Microsoft YaHei;
            font-weight: 400;
            line-height: 14px;
            color: #28b1e4;
            cursor: pointer;

            &:hover {
              text-decoration: underline;
            }
          }
        }

        .property {
          display: flex;
          align-items: center;

          margin-top: 10px;
          padding-left: 5px;

          &:last-of-type {
            margin-bottom: 10px;
          }

          & > span {
            font-size: 14px;
            font-family: Microsoft YaHei;
            font-weight: 400;
            line-height: 14px;

            &:nth-of-type(1) {
              margin-right: 8px;
              color: #27475f;
            }

            &:nth-of-type(2) {
              flex: 1;
              color: #717689;
            }
          }
        }

        .operation {
          display: flex;
          justify-content: center;
          align-items: center;

          padding: 10px 0;

          .button {
            display: flex;
            justify-content: center;
            align-items: center;

            width: 80px;
            height: 32px;
            border-radius: 2px;
            cursor: pointer;

            & > span {
              font-size: 14px;
              line-height: 14px;
              font-family: Arial;
            }

            &.reject {
              background-color: white;
              border: 1px solid $primary-color;

              &:hover {
                background-color: var(--el-button-hover-bg-color);
              }

              & > span {
                color: $primary-color;
              }
            }

            &.pass {
              background-color: $primary-color;

              & > span {
                color: white;
              }
            }
          }

          .button + .button {
            margin-left: 9px;
          }
        }
      }
    }
  }
}
</style>
